﻿using Communergy.Repository.InMemory;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Communergy.Common;
using System;

namespace Communergy.Repository.InMemory.Tests
{
    
    
    /// <summary>
    ///This is a test class for InMemoryMeterRepositoryTest and is intended
    ///to contain all InMemoryMeterRepositoryTest Unit Tests
    ///</summary>
    [TestClass()]
    public class InMemoryMeterRepositoryTest
    {


        private TestContext testContextInstance;
        

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion


        /// <summary>
        ///A test for CreateNewMeter
        ///</summary>
        [TestMethod()]
        public void InMemoryMeterRepository_CreateASimpleNewMeter_ShouldBeSaved()
        {
            InMemoryUnitOfWork unitOfWork = new InMemoryUnitOfWork();
            InMemoryMeterRepository meterRepository = new InMemoryMeterRepository(unitOfWork);
            Meter meterToCreate = InMemoryTestHelpers.GetTestMeter();           
           
            meterRepository.CreateNewMeter(meterToCreate);
            unitOfWork.Save();

            Assert.AreEqual(1, unitOfWork.Meters.Count);
        }

       


        /// <summary>
        ///A test for CreateNewMeter
        ///</summary>
        [TestMethod()]
        public void InMemoryMeterRepository_CreateASimpleNewMeterWithoutSave_ShouldBePending()
        {
            MockInMemoryUnitOfWork unitOfWork = new MockInMemoryUnitOfWork();
            InMemoryMeterRepository meterRepository = new InMemoryMeterRepository(unitOfWork);
            Meter meterToCreate = new Meter { MeterName = "Meter" };

            meterRepository.CreateNewMeter(meterToCreate);
            

            Assert.AreEqual(1, unitOfWork.MetersPending.Count);
        }


        /// <summary>
        ///A test for CreateNewMeter
        ///</summary>
        [TestMethod()]
        public void InMemoryMeterRepository_CreateAndRetrieveSimpleNewMeter_ShouldBeRetrieved()
        {
            InMemoryUnitOfWork unitOfWork = new InMemoryUnitOfWork();
            InMemoryMeterRepository meterRepository = new InMemoryMeterRepository(unitOfWork);
            Meter meterToCreate = InMemoryTestHelpers.GetTestMeter();

            meterRepository.CreateNewMeter(meterToCreate);
            unitOfWork.Save();

            var retrievedMeter = meterRepository.RetrieveMeterDetails(meterToCreate.MeterId);
            Assert.IsNotNull(retrievedMeter);

        }

        /// <summary>
        ///A test for CreateNewMeter
        ///</summary>
        [TestMethod()]
        public void InMemoryMeterRepository_CreateAndRetrieveSimpleNewMeter_ShouldBeCorrectItemRetrieved()
        {
            InMemoryUnitOfWork unitOfWork = new InMemoryUnitOfWork();
            InMemoryMeterRepository meterRepository = new InMemoryMeterRepository(unitOfWork);
            Meter meterToCreate = InMemoryTestHelpers.GetTestMeter();

            meterRepository.CreateNewMeter(meterToCreate);
            unitOfWork.Save();

            var retrievedMeter = meterRepository.RetrieveMeterDetails(meterToCreate.MeterId);

            string meterName = InMemoryTestHelpers.METER_NAME;

            Assert.AreEqual(meterName, retrievedMeter.MeterName);

        }

        /// <summary>
        ///A test for AddSourceToMeter
        ///</summary>
        [TestMethod()]
        public void InMemoryMeterRepository_CreateMeterAndAddNewSource_SourceWillBeInPendingList()
        {
            MockInMemoryUnitOfWork unitOfWork = new MockInMemoryUnitOfWork();
            InMemoryMeterRepository meterRepository = new InMemoryMeterRepository(unitOfWork);
            Meter meterToCreate = InMemoryTestHelpers.GetTestMeter();

            meterRepository.CreateNewMeter(meterToCreate);
            unitOfWork.Save();

            MeterSource meterSource = InMemoryTestHelpers.GetTestSource();
            meterRepository.AddSourceToMeter(meterToCreate, meterSource);
            Assert.AreEqual(1, unitOfWork.MeterSourcesPending.Count);
        }

        [TestMethod()]
        public void InMemoryMeterRepository_CreateMeterAndAddNewSource_MeterWillBeInPendingList()
        {
            MockInMemoryUnitOfWork unitOfWork = new MockInMemoryUnitOfWork();
            InMemoryMeterRepository meterRepository = new InMemoryMeterRepository(unitOfWork);
            Meter meterToCreate = InMemoryTestHelpers.GetTestMeter();

            meterRepository.CreateNewMeter(meterToCreate);
            unitOfWork.Save();

            MeterSource meterSource = InMemoryTestHelpers.GetTestSource();
            meterRepository.AddSourceToMeter(meterToCreate, meterSource);

            var pendingRecord = unitOfWork.MeterSourcesPending[0];
            Assert.AreEqual(InMemoryTestHelpers.METER_ID, pendingRecord.Meter.MeterId);
        }

        [TestMethod()]
        public void InMemoryMeterRepository_CreateMeterAndAddNewSource_MeterSourceWillBeInPendingList()
        {
            MockInMemoryUnitOfWork unitOfWork = new MockInMemoryUnitOfWork();
            InMemoryMeterRepository meterRepository = new InMemoryMeterRepository(unitOfWork);
            Meter meterToCreate = InMemoryTestHelpers.GetTestMeter();

            meterRepository.CreateNewMeter(meterToCreate);
            unitOfWork.Save();

            MeterSource meterSource = InMemoryTestHelpers.GetTestSource();
            meterRepository.AddSourceToMeter(meterToCreate, meterSource);

            var pendingRecord = unitOfWork.MeterSourcesPending[0];
            Assert.AreEqual(InMemoryTestHelpers.METER_SOURCE_NAME, pendingRecord.MeterSource.Name);
        }


        /// <summary>
        ///A test for AddSourceToMeter
        ///</summary>
        [TestMethod()]
        public void InMemoryMeterRepository_CreateMeterAddNewSourceAndSave_PendingListWillBeEmpty()
        {
            MockInMemoryUnitOfWork unitOfWork = new MockInMemoryUnitOfWork();
            InMemoryMeterRepository meterRepository = new InMemoryMeterRepository(unitOfWork);
            Meter meterToCreate = InMemoryTestHelpers.GetTestMeter();

            meterRepository.CreateNewMeter(meterToCreate);
            unitOfWork.Save();

            MeterSource meterSource = InMemoryTestHelpers.GetTestSource();
            meterRepository.AddSourceToMeter(meterToCreate, meterSource);
            unitOfWork.Save();
            Assert.AreEqual(0, unitOfWork.MeterSourcesPending.Count);
        }

        [TestMethod()]
        public void InMemoryMeterRepository_CreateMeterAddNewSourceAndSave_MeterSourceWillBeAddedToCorrectMeter()
        {
            MockInMemoryUnitOfWork unitOfWork = new MockInMemoryUnitOfWork();
            InMemoryMeterRepository meterRepository = new InMemoryMeterRepository(unitOfWork);
            Meter meterToCreate = InMemoryTestHelpers.GetTestMeter();

            meterRepository.CreateNewMeter(meterToCreate);
            unitOfWork.Save();

            MeterSource meterSource = InMemoryTestHelpers.GetTestSource();
            meterRepository.AddSourceToMeter(meterToCreate, meterSource);
            unitOfWork.Save();

            var retrievedMeter = meterRepository.RetrieveMeterDetails(InMemoryTestHelpers.METER_ID);
            Assert.AreEqual(1, retrievedMeter.Sources.Count);
        }

        [TestMethod()]
        public void InMemoryMeterRepository_CreateMeterAddNewSourceAndSave_CorrectMeterSourceWillBeAddedToCorrectMeter()
        {
            MockInMemoryUnitOfWork unitOfWork = new MockInMemoryUnitOfWork();
            InMemoryMeterRepository meterRepository = new InMemoryMeterRepository(unitOfWork);
            Meter meterToCreate = InMemoryTestHelpers.GetTestMeter();

            meterRepository.CreateNewMeter(meterToCreate);
            unitOfWork.Save();

            MeterSource meterSource = InMemoryTestHelpers.GetTestSource();
            meterRepository.AddSourceToMeter(meterToCreate, meterSource);
            unitOfWork.Save();

            var retrievedMeter = meterRepository.RetrieveMeterDetails(InMemoryTestHelpers.METER_ID);
            var retreivedSource = retrievedMeter.Sources[0];
            Assert.AreEqual(InMemoryTestHelpers.METER_SOURCE_NAME, retreivedSource.Name);
        }



        [TestMethod()]
        public void InMemoryMeterRepository_CreateMeterAddNewSourceAndSave_RetrieveSourceById()
        {
            MockInMemoryUnitOfWork unitOfWork = new MockInMemoryUnitOfWork();
            InMemoryMeterRepository meterRepository = new InMemoryMeterRepository(unitOfWork);
            Meter meterToCreate = InMemoryTestHelpers.GetTestMeter();

            meterRepository.CreateNewMeter(meterToCreate);
            unitOfWork.Save();

            MeterSource meterSource = InMemoryTestHelpers.GetTestSource();
            meterRepository.AddSourceToMeter(meterToCreate, meterSource);
            unitOfWork.Save();

            var retreivedSource = meterRepository.RetrieveSourceDetails(InMemoryTestHelpers.METER_SOURCE_ID);
           
            Assert.AreEqual(InMemoryTestHelpers.METER_SOURCE_NAME, retreivedSource.Name);
        }


        [TestMethod()]
        public void InMemoryMeterRepository_CreateMeterAddNewSourceAndSaveRetrieveSourceUnknownSource_ShouldBeNull()
        {
            MockInMemoryUnitOfWork unitOfWork = new MockInMemoryUnitOfWork();
            InMemoryMeterRepository meterRepository = new InMemoryMeterRepository(unitOfWork);
            Meter meterToCreate = InMemoryTestHelpers.GetTestMeter();

            meterRepository.CreateNewMeter(meterToCreate);
            unitOfWork.Save();

            MeterSource meterSource = InMemoryTestHelpers.GetTestSource();
            meterRepository.AddSourceToMeter(meterToCreate, meterSource);
            unitOfWork.Save();

            var nullSource = meterRepository.RetrieveSourceDetails(Guid.NewGuid().ToString());

            Assert.IsNull(nullSource);
        }
    }
}
